/*
 * auto_proxy.c
 *
 * Created: 12/3/2011 11:53:30 AM
 *  Author: cmason1
 */ 

#define F_CPU 10000000UL  // 10 MHz

#include <avr/io.h>
// #include <avr/interrupt.h>
#include <util/delay.h>

// #define sei()
// #define cli()

// #define PWM0_ON TCCR0A |= 2 << COM0A0; //turns non-inverting PWM0 on
// #define PWM0_OFF TCCR0A &= 0b00111111;//turns non-inverting PWM0 off
#define PWM1A_ON TCCR1A |= 2 << COM1A0; //turns non-inverting PWM1A on
#define PWM1A_OFF TCCR1A &= 0b00111111;//turns non-inverting PWM1A off
// #define PWM1B_ON TCCR1A |= 2 << COM1B0; //turns non-inverting PWM1B on
// #define PWM1B_OFF TCCR1A &= 0b11001111;//turns non-inverting PWM1B off

#define CounterON TCCR2A |= 2<<COM2A0;
#define CounterOFF TCCR2A &= 0b00111111;

const int ADC_OFFSET = 3;

volatile int tenthmS;

// BCD for displaying number to 7 segment LED
char num[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
int k,i,led1,led2,led3;
// k is the value for display
// led1 is displayed in LED1
//led2 is displayed in LED2
//led3 is displayed in LED3

//DO NOT USE EXCEPT TO EXIT LOOPS!//
int delayloop( uint16_t ms )
{
	while ( ms ) 
	{
		_delay_ms( 1 );
		ms--;
	}
	return 0;  //return int to exit loops
}
void delayms( uint16_t ms )
{
	while (ms)
	{
		_delay_ms(1);
		ms--;
	}
}


// ISR (TIMER2_OVF_vect)
// {
// 	tenthmS++;
// }

void PWM_init()
{
// 	TCCR0A = 0; // turns off timer 0-A
	TCCR1A = 0; // turns off timer 1-A
// 	TCCR1B = 0; // turns off timer 1-B
	TCCR2A = 0; // turns off timer 2-A

   ICR1 = 249; /* TOP seen above for timer 1 */
      
//   TCCR0A |= (1 << WGM01) | (1 << WGM00); // sets timer0 to Fast PWM
//   TCCR0B |= (1<<WGM02)| (1<<CS00);
   TCCR1A |= (1 << WGM11); // this and next line sets timer1 to
   TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1<<CS10); // Fast PWM with prescaler=1
   TCCR2A |= (1<<CS20) | (1<<COM2A0); //prescaler=1 for 74.4kHz or 13 ms period
   TCNT2 = 0;
//   TIMSK2 |= (1<<OCIE2A);
//   DDRD |= _BV(6);   // enable PD6 as output pin
   DDRB |= _BV(1) | _BV(3);// | _BV(2); // enables PB1&PB2 as output pins
   
//    TCCR0A |= 2 << 6; // sets COM0A(0&1) to 0x10 = non-inverting turns channel on
   TCCR1A |= 2 << 6; // sets COM1A(0&1) to 0x10 = non-inverting turns channel on
//   TCCR1A |= 2 << 4; // sets COM1B(0&1) to 0x10 = non-inverting turns channel on
//    CounterON;
/*   OCR0A = 250/2;  //sets the frequency to 40kHz*/
   OCR1A = 250/2; //sets the frequency to 40kHz with 50% duty cycle 
//    OCR1B = 250/2; //sets the frequency to 40kHz
   OCR2A = 134/2; //sets the frequency to 10kHz
}

void ADC_init()
{
	//selects reference voltage to be external aka AREF
	ADMUX = 1<<REFS0; 
	
	//enables ADC to operate at 156kHz and is triggered automatically
	ADCSRA = (1<<ADEN) | (6<<ADPS0) | (1<<ADATE);
}

int ADC_getTime(int channel)
{
	ADMUX &= 0xE0; //disables whatever ADC channel is activated
	ADMUX |= (channel+ADC_OFFSET)<<MUX0;
	
	int time=0;
// 	int dumby;
	
	_delay_ms(1); //waits until after 6inches, also until echo subsides
	
	TCNT2 = 0; // assumes the count started at 0
	while(TCNT2<9)
	{
		
	}
//	CounterON;
//	sei();
// 	dumby = TCNT2;
// 	
	while(ADC < 6 && TCNT2 < 255) //while the value of of the return signal is less than 5mV*6
	{
// 		if(dumby < TCNT2)
// 		{
// 			tenthmS++;
// 			dumby = TCNT2;
// 		}
	}
		
	CounterOFF;
//	cli();
	
	if(ADC > 6)
	{
		time = TCNT2;
	}
	
	return time;
}

void Calc_Display(double seconds)
{	 
	 k= seconds*10*1116.43/2; //distance*10
   	 led3 = (k-k%100)/100;   
	 led2 = (k%100-k%10)/10;
	 led1 = k%10;
     DDRD =0xFF; // Port B is set as output
	 DDRC =0x07; // pin 0th, 1st and 2nd are set as output
	for (i=1000;i>0;i=i-3)  //update LEDs for 1 second
	 {
		 PORTC =0x01; // Turn on the LED1
		 PORTD = num[led1];// Display value led1 on LED1
		 delayms(1);  //POV time (30 ms to display each digit)
		 PORTC =0x02; // Turn on the LED2
		 PORTD = num[led2];// Display value led2 on LED2
		 delayms(1);  //POV time (30 ms to display each digit)
		 PORTC =0x04; // Turn on the LED3
		 PORTD = num[led3];// Display value led3 on LED3
		 delayms(1);  //POV time (30 ms to display each digit)
	 }	 
}
int main(void)
{
  	PWM_init();
	ADC_init();
	
	while(1)
    {
		int channel = 0;
		double num100uS = .008;
		 
// 		PWM0_ON; //turns non-inverting PWM0 on
// 		_delay_us(200);
// 		PWM0_OFF;
// 		num100uS = ADC_getTime(channel);
// 		if(num100uS!=0)
// 		{
// 			Calc_Display(num100uS*.0001);
// 		}
		channel++;
		PWM1A_ON;
		_delay_us(200);
		PWM1A_OFF;
//		num100uS = ADC_getTime(channel);
		
		if(num100uS!=0)
		{
			Calc_Display(num100uS);
		}
// 		channel++;
// 		PWM1B_ON;
// 		_delay_us(200);
// 		PWM1B_OFF;
// 		num100uS = ADC_getTime(channel);
// 		
// 		if(num100uS!=0)
// 		{
// 			Calc_Display(num100uS*.0001);
// 		}
    }
}